﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace CommonLib.CameraExtend
{
	[RequireComponent(typeof(Camera))]
	public class CameraBoxControl : MonoBehaviour
	{
		[SerializeField]
		CameraInfor cameraInfor;
		public CameraInfor CameraInfor
		{
			get {
				if(null == cameraInfor)
				{
					cameraInfor = new CameraInfor();
				}
				return cameraInfor;
			}
			private set { cameraInfor = value; }
		}
		Camera cameraBox;

		float m_AspectRatio = 1;
		Vector2 m_Padding = Vector2.zero;
		bool hasChanged = true;

		Vector2 currentSize;
		public Vector2 CurrentSize
		{
			get
			{
				if (hasChanged)
				{
					RefreshCurrentSize();
				}
				return currentSize;
			}
		}

		//2D（OrthoGrahpic）の場合のズーム倍率
		public float Zoom2D
		{
			get
			{
				return CameraInfor.m_Zoom;
			}
			set
			{
				CameraInfor.m_Zoom = value;
				hasChanged = true;
			}
		}

		//2D（OrthoGrahpic）の場合のズーム中心点
		public Vector2 Zoom2DCenter
		{
			get
			{
				return CameraInfor.m_ZoomCenter;
			}
			set
			{
				CameraInfor.m_ZoomCenter = value;
				hasChanged = true;
			}
		}



		internal void SetZoom2D(float zoom, Vector2 center)
		{
			this.Zoom2D = zoom;
			this.Zoom2DCenter = center;
		}

		public void Awake()
		{
			//初始化Camera
			cameraBox = GetComponent<Camera>();
			if(null != cameraBox)
			{
				CameraInfor.SetCameraByInfor(cameraBox);
			}
		}

		private void Start()
		{
			hasChanged = true;
		}
		private void Update()
		{
			if(hasChanged || !Mathf.Approximately(m_AspectRatio, 1.0f * Screen.width / Screen.height))
				Refresh();
		}

		void Refresh()
		{
			hasChanged = false;
			RefreshCurrentSize();
			RefreshCamera();
		}


		void RefreshCurrentSize()
		{
			if (TryRefreshCurrentSize())
			{
				Debug.Log($"{ cameraBox.name} has been change");
			}
		}

		bool TryRefreshCurrentSize()
		{
			m_AspectRatio = 1.0f * Screen.width / Screen.height;

			float defaultAspectRatio = (float)CameraInfor.m_Width / CameraInfor.m_Height;       //默认设置的长宽比
			float wideAspectRatio = (float)CameraInfor.m_MaxWidth / CameraInfor.m_MinHeight;   //最大的长宽比
			float nallowAspectRatio = (float)CameraInfor.m_MinWidth / CameraInfor.m_MaxHeight; //最小的长款比

			int w, h;
			if (m_AspectRatio > wideAspectRatio)
			{

				m_Padding.x = (1.0f - wideAspectRatio / m_AspectRatio) / 2;
				m_Padding.y = 0;

				w = CameraInfor.m_MaxWidth;   //横は最大を
				h = CameraInfor.m_MinHeight;  //縦は最小を
			}
			else if (m_AspectRatio < nallowAspectRatio)
			{
				m_Padding.x = 0;
				m_Padding.y = (1.0f - m_AspectRatio / nallowAspectRatio) / 2;

				w = CameraInfor.m_MinWidth;   //横は最大を
				h = CameraInfor.m_MaxHeight;  //縦は最小を
			}
			else
			{
				m_Padding.x = 0;
				m_Padding.y = 0;

				if (Mathf.Approximately(m_AspectRatio, defaultAspectRatio))
				{
					//基本的なアスペクト比と同じ
					w = CameraInfor.m_Width;
					h = CameraInfor.m_Height;
				}
				else
				{
					h = CameraInfor.m_MinHeight;
					w = Mathf.FloorToInt(m_AspectRatio * h);
					if (w < CameraInfor.m_MinWidth)
					{
						w = CameraInfor.m_MinWidth;
						h = Mathf.FloorToInt(w / m_AspectRatio);
					}
				}
			}

			bool changed = (currentSize.x != w) || (currentSize.y != h);
			currentSize = new Vector2(w, h);
			return changed;
		}


		void RefreshCamera()
		{
			float x = m_Padding.x;
			float width = 1 - m_Padding.x * 2;
			float y = m_Padding.y;
			float height = 1 - m_Padding.y * 2;

			switch (CameraInfor.m_Anchor)
			{
				case AnchorType.UpperLeft:
					x = 0;
					y = m_Padding.y * 2;
					break;
				case AnchorType.UpperCenter:
					y = m_Padding.y * 2;
					break;
				case AnchorType.UpperRight:
					x = m_Padding.x * 2;
					y = m_Padding.y * 2;
					break;
				case AnchorType.MiddleLeft:
					x = 0;
					break;
				case AnchorType.MiddleCenter:
					break;
				case AnchorType.MiddleRight:
					x = m_Padding.x * 2;
					break;
				case AnchorType.LowerLeft:
					x = 0;
					y = 0;
					break;
				case AnchorType.LowerCenter:
					y = 0;
					break;
				case AnchorType.LowerRight:
					x = m_Padding.x * 2;
					y = 0;
					break;
			}
			Rect rect = new Rect(x, y, width, height);
			cameraBox.orthographicSize = CurrentSize.y / (2 * CameraInfor.m_PixelsToUnits) / CameraInfor.m_Zoom;
			cameraBox.rect = rect;

			Vector2 zoom2DCenterOffset = (-1.0f / CameraInfor.m_Zoom + 1) * CameraInfor.m_ZoomCenter / (CameraInfor.m_PixelsToUnits);
			cameraBox.transform.localPosition = zoom2DCenterOffset;
		}
	}
}